home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Develop / Additional Articles / Developing Symbiotic Apps / Symbiotic Samples / Symbiotic server source / flexibled & simpled / ppcstuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-03  |  8.6 KB  |  285 lines  |  [TEXT/CWIE]

  1. /* ppcstuff.c -- PPC Toolbox calls for flexibled sample daemon.
  2.  *
  3.  * %W%
  4.  *
  5.  * Original Author: Chris Jalbert
  6.  * Copyright 1996 Apple Computer, Inc.
  7.  * All Rights Reserved.
  8.  *
  9.  * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
  10.  * The copyright notice above does not evidence any actual or
  11.  * intended publication of such source code.
  12.  *
  13.  * History:
  14.  * 8/19/96    Chris Jalbert
  15.  *    First checked in. Several ideas borrowed from DTS / Jim Luther's
  16.  *    Remote Control pascal sample.
  17.  */
  18.  
  19.  
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <time.h>
  23.  
  24. /* Includes for MacOS prototypes. */
  25. #include <Types.h>
  26. #include <Errors.h>
  27. #include <Script.h>        /* For smRoman #define. */
  28. #ifdef _AIX
  29. #include <PPCToolBox.h>
  30. #else
  31. #include <PPCToolbox.h>
  32. #endif
  33.  
  34. #include "tridentd.h"
  35. #include "debug.h"
  36.  
  37. #define kSigString    "\pJVLN"
  38.  
  39.  
  40. /******************************************************************************
  41.     ==>  Private Globals  <==
  42. ******************************************************************************/
  43. static LocationNameRec    _LocationRecord ;
  44. static PPCPortRec        _UptimeRecord
  45.                     = {smRoman, "\pNew Status Demo", ppcByCreatorAndType} ;
  46. static PPCPortRefNum    _UptimePort ;
  47. static PPCInformPBRec    _UptimePB ;
  48. static ClientPtr        _UptimeClient ;
  49. static PPCPortRec        _WhoRecord
  50.                     = {smRoman, "\pLogin Demo", ppcByCreatorAndType} ;
  51. static PPCPortRefNum    _WhoPort ;
  52. static PPCInformPBRec    _WhoPB ;
  53. static ClientPtr        _WhoClient ;
  54. static Str32            _NewUser ;
  55.  
  56.  
  57. /******************************************************************************
  58.     ==>  Static Callback Functions  <==
  59. ******************************************************************************/
  60. /*-----------------------------------------------------------------------------
  61.     There is no real reason that the Uptime and Who services shouldn't
  62.     share the same callback function because the services are identical
  63.     with the exception of the command names of their data sources. However,
  64.     most apps would offer services that may use different sets of AppleEvents,
  65.     so they would likely use separate callback functions to simplify coding.
  66. -----------------------------------------------------------------------------*/
  67. static pascal void _InformCallback (
  68.     PPCParamBlockPtr    pbParam)
  69.     {
  70.     PPCInformPBPtr        pb = &pbParam->informParam;
  71.     PPCParamBlockRec    param ;
  72.     OSErr                result ;
  73.  
  74.     /* These operations are valid for all sub-param blocks. */
  75.     memset (¶m, 0, sizeof (PPCParamBlockRec)) ;
  76.     param.endParam.sessRefNum = pb->sessRefNum ;
  77.  
  78.     /* Bail and close the connection if there was an error. */
  79.     if (pb->ioResult)
  80.         {
  81.         result = PPCEndSync (¶m.endParam) ;
  82.         return ;
  83.         }
  84.  
  85. #if _DEBUG
  86.     {
  87.     time_t                tCurrent = time (NULL) ;
  88.     DBGM (tprintf ("\n------------------- %s"
  89.                     "New %s user '%s' on conn #%ld.\n",
  90.                 asctime (localtime (&tCurrent)),
  91.                 ((pb->portRefNum == _WhoPort) ? "WHO" : "UPTIME"),
  92.                 (*pb->userName ? (char *) &pb->userName[1] : "<Mac guest>"),
  93.                 pb->sessRefNum)) ;
  94.     }
  95. #endif
  96.  
  97.     /* Tell the client that it has been accepted. */
  98.     if (result = PPCAcceptSync (¶m.acceptParam))
  99.         {
  100.         DBG ("Yikes! PPCAccept returned %d!\n", result) ;
  101.         /* Need to issue an end if accept failed. */
  102.         memset (¶m, 0, sizeof (PPCParamBlockRec)) ;
  103.         param.endParam.sessRefNum = pb->sessRefNum ;
  104.         result = PPCEndSync (¶m.endParam) ;
  105.         return ;
  106.         }
  107.  
  108.     /* Fill in the connection object. */
  109.     if (pb->portRefNum == _WhoPort)
  110.         {
  111.         ClientSetSession (_WhoClient, pb->sessRefNum) ;
  112.         _WhoClient = NULL ;
  113.         }
  114.     else if (pb->portRefNum == _UptimePort)
  115.         {
  116.         ClientSetSession (_UptimeClient, pb->sessRefNum) ;
  117.         _UptimeClient = NULL ;
  118.         }
  119.     }
  120.  
  121.  
  122.  
  123. /******************************************************************************
  124.     ==>  Global (Exported) Functions  <==
  125. ******************************************************************************/
  126.  
  127. /*-----------------------------------------------------------------------------
  128.     PPCTimeSlice really isn't necessary on AIX -- all the necessary
  129.     processing can occur inside the inform callback -- but including it
  130.     allows the same source code to run on both MacOS and AIX. Nifty, huh?
  131. -----------------------------------------------------------------------------*/
  132. OSErr PPCTimeSlice (void)
  133.     {
  134.     OSErr            result ;
  135.  
  136.     if (_WhoClient == NULL)
  137.         if (NULL == (_WhoClient = NewClient (kWhoType)))
  138.             return memFullErr ;
  139.     if (_UptimeClient == NULL)
  140.         if (NULL == (_UptimeClient = NewClient (kUptimeType)))
  141.             return memFullErr ;
  142.  
  143.     /* Tell the system that the app is ready to handle connections. */
  144.     if (_UptimePB.ioResult != 1)
  145.         if (result = PPCInformAsync (&_UptimePB))
  146.             return result ;
  147.     if (_WhoPB.ioResult != 1)
  148.         if (result = PPCInformAsync (&_WhoPB))
  149.             return result ;
  150.     return result ;
  151.     }
  152.     
  153. /*-----------------------------------------------------------------------------
  154.     InitPPCStuff initializes the PPC library, opens (registers) two
  155.     listening ports, one for 'uptime' and one for 'who' connections, and
  156.     notifies the PPC TB that it is ready to accept connections.
  157. -----------------------------------------------------------------------------*/
  158. OSErr InitPPCStuff (void)
  159.     {
  160.     PPCOpenPBRec    openBlock ;
  161.     OSErr            err ;
  162.  
  163.     /* Init the library (and stream to ppcd on AIX). */
  164.     PPCInit () ;
  165.  
  166.  
  167.     /*** Define and open two ports, one for uptime and one for who. ***/
  168.  
  169.     /* Fill in location record. */
  170.     _LocationRecord.locationKindSelector = ppcNBPTypeLocation ;
  171.     strcpy ((char *) _LocationRecord.u.nbpType, (char *) kSigString) ;
  172.  
  173.     /* Define the open param block. */
  174.     memset (&openBlock, 0, sizeof (PPCOpenPBRec)) ;
  175.     openBlock.ioCompletion = NULL ;
  176.     openBlock.serviceType = ppcServiceRealTime ;
  177.     openBlock.locationName = &_LocationRecord ;
  178.     openBlock.networkVisible = true ;
  179.  
  180.     /* Fill in and register port info for uptime command. */
  181.     /* Unions can't be filled statically. */
  182. #ifdef _AIX
  183.     /* The Universal Headers guys changed the struct field names
  184.      * between versions!!!!
  185.      */
  186.     _UptimeRecord.u.port.creator = kSignature ;
  187.     _UptimeRecord.u.port.type = kUptimeType ;
  188. #else
  189.     _UptimeRecord.u.port.portCreator = kSignature ;
  190.     _UptimeRecord.u.port.portType = kUptimeType ;
  191. #endif    /* _AIX */
  192.     openBlock.portName = &_UptimeRecord ;
  193.     if (err = PPCOpenSync (&openBlock))
  194.         return err ;
  195.     _UptimePort = openBlock.portRefNum ;
  196.  
  197.     /* Fill in and register port info for who command. */
  198. #ifdef _AIX
  199.     _WhoRecord.u.port.creator = kSignature ;
  200.     _WhoRecord.u.port.type = kWhoType ;
  201. #else
  202.     _WhoRecord.u.port.portCreator = kSignature ;
  203.     _WhoRecord.u.port.portType = kWhoType ;
  204. #endif    /* _AIX */
  205.     openBlock.portName = &_WhoRecord ;
  206.     if (err = PPCOpenSync (&openBlock))
  207.         return err ;
  208.     _WhoPort = openBlock.portRefNum ;
  209.  
  210.     /* Fill in the global structures this one time and never again! */
  211.     _UptimePB.ioCompletion = NewPPCCompProc (_InformCallback) ;
  212.     _UptimePB.portRefNum = _UptimePort ;
  213.     _UptimePB.autoAccept = false ;
  214.     _UptimePB.portName = &_UptimeRecord ;
  215.     _UptimePB.locationName = &_LocationRecord ;
  216.     _UptimePB.userName = _NewUser ;
  217.  
  218.     _WhoPB.ioCompletion = NewPPCCompProc (_InformCallback) ;
  219.     _WhoPB.portRefNum = _WhoPort ;
  220.     _WhoPB.autoAccept = false ;
  221.     _WhoPB.portName = &_WhoRecord ;
  222.     _WhoPB.locationName = &_LocationRecord ;
  223.     _WhoPB.userName = _NewUser ;
  224.  
  225.     /* The inform calls will be made by PPCTimeSlice when the daemon enters
  226.      * its main loop. It does not make sense to tell ppcd now that it is
  227.      * ready to accept connections if there is more startup overhead.
  228.      */
  229.     return err ;
  230.     }
  231.  
  232.  
  233. OSErr CloseClient (
  234.     ClientPtr    conn)
  235.     {
  236.     PPCEndPBRec    end ;
  237.  
  238.     memset (&end, 0, sizeof (PPCEndPBRec));
  239.     end.sessRefNum = conn->session ;
  240.     DeleteClient (conn) ;
  241.     return PPCEndSync (&end) ;
  242.     }
  243.  
  244.  
  245. /*-----------------------------------------------------------------------------
  246.     PPCShutDown closes (unregisters) the two listening ports. The Toolbox
  247.     could close all outstanding connections, but this functions closes
  248.     them before to free memory and be a nice client.
  249. -----------------------------------------------------------------------------*/
  250. OSErr PPCShutDown (void)
  251.     {
  252.     PPCParamBlockRec    param ;
  253.     PPCClosePBPtr        close = ¶m.closeParam ;
  254.     PPCEndPBPtr            end = ¶m.endParam ;
  255.     ClientPtr            last ;
  256.     OSErr                err, err2 ;
  257.  
  258.     memset (¶m, 0, sizeof (PPCParamBlockRec));
  259.     while (UptimeClients)
  260.         {
  261.         end->sessRefNum = UptimeClients->session ;
  262.         err = PPCEndSync (end) ;
  263.         last = UptimeClients ;
  264.         UptimeClients = UptimeClients->qLink ;
  265.         free (last) ;
  266.         }
  267.     while (WhoClients)
  268.         {
  269.         end->sessRefNum = WhoClients->session ;
  270.         err = PPCEndSync (end) ;
  271.         last = WhoClients ;
  272.         WhoClients = WhoClients->qLink ;
  273.         free (last) ;
  274.         }
  275.  
  276.     /* Define the close param block. */
  277.     memset (¶m, 0, sizeof (PPCParamBlockRec)) ;
  278.     close->ioCompletion = NULL ;
  279.     close->portRefNum = _UptimePort ;
  280.     err = PPCCloseSync (close) ;
  281.     close->portRefNum = _WhoPort ;
  282.     err2 = PPCCloseSync (close) ;
  283.     return (err ? err : err2) ;
  284.     }
  285.